logo

1.Introduction

In this project, we analyze time series forecasting using Meta’s Prophet model. Prophet is a powerful and user-friendly tool for forecasting time series data, commonly applied in predicting financial trends, stock prices, and market movements.

We will implement Prophet to forecast the EuStockMarkets dataset, which contains historical daily closing prices for major European stock indices.My objective is to develop a forecasting model, predict future stock prices, and evaluate the accuracy of these predictions.

For this analysis, we will use the R implementation of Prophet to generate insights into market trends, seasonality, and long-term financial patterns.

1.1 What is the EuStockMarkets Dataset?

The built-in EuStockMarkets dataset in R provides daily closing prices for four major European stock indices from 1991 to 1998:

  • Stock indices included:
    • DAX (Germany)
    • SMI (Switzerland)
    • CAC (France)
    • FTSE (UK)

This dataset is stored as a ts (time series) object, meaning it has a structured time index. To use it in Prophet, I will convert it into a data frame.

2.Data preparation

2.1Display dataset structure and statistics

str(EuStockMarkets)
##  Time-Series [1:1860, 1:4] from 1991 to 1999: 1629 1614 1607 1621 1618 ...
##  - attr(*, "dimnames")=List of 2
##   ..$ : NULL
##   ..$ : chr [1:4] "DAX" "SMI" "CAC" "FTSE"
summary(EuStockMarkets)
##       DAX            SMI            CAC            FTSE     
##  Min.   :1402   Min.   :1587   Min.   :1611   Min.   :2281  
##  1st Qu.:1744   1st Qu.:2166   1st Qu.:1875   1st Qu.:2843  
##  Median :2141   Median :2796   Median :1992   Median :3247  
##  Mean   :2531   Mean   :3376   Mean   :2228   Mean   :3566  
##  3rd Qu.:2722   3rd Qu.:3812   3rd Qu.:2274   3rd Qu.:3994  
##  Max.   :6186   Max.   :8412   Max.   :4388   Max.   :6179

Key Takeaways

1)Swiss Market (SMI) had the highest stock values overall.

-Highest median (2796), mean (3376), and max (8412) Indicates strong performance and growth over time.

2)FTSE (UK) showed strong performance but was more stable.

-Higher quartile values and mean (3566) suggest a more consistent upward trend. -Lower volatility compared to DAX and CAC.

3)DAX (Germany) had the lowest minimum (1402) but strong growth.

-Large gap between min (1402) and max (6186), suggesting higher volatility. -Fast growth and high fluctuation compared to FTSE and SMI.

4)CAC (France) had the lowest max (4388) and relatively lower values overall.

-Suggests it was the least volatile but also had lower peaks.

The objective of this coursework is to:

Analyze the historical trends of European stock indices. Use Prophet forecasting to predict future stock prices. Visualize trends, seasonality, and forecast components. Apply statistical techniques (e.g., linear regression) to understand growth patterns. Compare time frames to see how market trends evolve over time.

## Load necessary packages
library(prophet)  # Forecasting model
## Loading required package: Rcpp
## Loading required package: rlang
library(zoo)      # Date handling
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(ggplot2)# Visualization
library(dplyr)    # Data manipulation
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

2.2 Convert EuStockMarkets to a DataFrame with Correct Date Conversion

eustock.df <- data.frame(
  ds = as.Date(as.yearmon(time(EuStockMarkets))),  # Convert to Year-Month format & Date
  y = as.numeric(EuStockMarkets[, "DAX"])                     # Select DAX stock index (Germany)
)

#Check the first few rows:
head(eustock.df)
##           ds       y
## 1 1991-06-01 1628.75
## 2 1991-07-01 1613.63
## 3 1991-07-01 1606.51
## 4 1991-07-01 1621.04
## 5 1991-07-01 1618.16
## 6 1991-07-01 1610.61
#Summary of the dataset:
summary(eustock.df)
##        ds                   y       
##  Min.   :1991-06-01   Min.   :1402  
##  1st Qu.:1993-04-01   1st Qu.:1744  
##  Median :1995-01-01   Median :2141  
##  Mean   :1995-01-11   Mean   :2531  
##  3rd Qu.:1996-11-01   3rd Qu.:2722  
##  Max.   :1998-08-01   Max.   :6186

Observations:

The minimum and maximum values of the DAX index show its growth over time. The mean and median values indicate the typical stock price level. The spread (range & standard deviation) suggests market volatility.

2.3 Visualizing Historical stock Prices

#Plot historical DAX prices:
ggplot(eustock.df, aes(x = ds, y = y)) +
  geom_line(color = "blue") +
  labs(title = "DAX Stock Prices (1991-1998)",
       x = "Year",
       y = "Stock Price") +
  theme_minimal()

Insights:

The stock market trends upwards, reflecting economic growth. There are short-term fluctuations, indicating market volatility.

While the static ggplot2 plot in Section 2.3 shows historical trends, it lacks interactivity. To enhance analysis, we use Plotly and Dygraphs, allowing zooming, dynamic comparisons, and real-time insights. These tools provide a more flexible and detailed exploration of stock price movements.

3.Exploratory Data Analysis

Before applying Prophet forecasting, we first analyze historical stock trends to ensure accurate predictions. Section 3 explores price movements, volatility, and long-term growth patterns through visualizations, statistical models, and interactive tools. By examining trends, seasonality, and different time periods, we gain insights into market behavior, helping us refine our forecasting approach. This step is crucial for identifying patterns, anomalies, and key growth factors, ensuring that our predictions in Section 4 are data-driven and reliable

3.1Interactive Visualizations with Plotly & Dygraphs

# Load interactive visualization libraries
library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
library(dygraphs)
#Convert ggplot2 chart to an interactive Plotly chart
plotly_chart <- ggplot(eustock.df, aes(x = ds, y = y)) +
  geom_line(color = "blue") +
  labs(title = "DAX Stock Prices (1991-1998)",
       x = "Year",
       y = "Stock Price") +
  theme_minimal()

#Convert to interactive Plotly
ggplotly(plotly_chart)

3.2Convert DataFrame to time-series format for Dygraphs

library(xts)  # Required for dygraphs
## 
## ######################### Warning from 'xts' package ##########################
## #                                                                             #
## # The dplyr lag() function breaks how base R's lag() function is supposed to  #
## # work, which breaks lag(my_xts). Calls to lag(my_xts) that you type or       #
## # source() into this session won't work correctly.                            #
## #                                                                             #
## # Use stats::lag() to make sure you're not using dplyr::lag(), or you can add #
## # conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop           #
## # dplyr from breaking base R's lag() function.                                #
## #                                                                             #
## # Code in packages is not affected. It's protected by R's namespace mechanism #
## # Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning.  #
## #                                                                             #
## ###############################################################################
## 
## Attaching package: 'xts'
## The following objects are masked from 'package:dplyr':
## 
##     first, last
eustock_ts <- xts(eustock.df$y, order.by = eustock.df$ds)

#Create an interactive Dygraph chart
dygraph(eustock_ts, main = "DAX Stock Prices (1991-1998)") %>%
  dyRangeSelector() %>% # Add a range selector to zoom into specific years
  dyAxis("y", label = "Stock Price") %>%
  dySeries("V1", label = "DAX") %>%
  dyOptions(strokeWidth = 2)
# Fit a linear model
lm_model <- lm(y ~ ds, data = eustock.df)

# Display summary of the regression
summary(lm_model)
## 
## Call:
## lm(formula = y ~ ds, data = eustock.df)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -779.95 -524.79  -38.92  383.67 2096.46 
## 
## Coefficients:
##               Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -8.722e+03  1.581e+02  -55.16   <2e-16 ***
## ds           1.231e+00  1.724e-02   71.41   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 560.7 on 1858 degrees of freedom
## Multiple R-squared:  0.733,  Adjusted R-squared:  0.7328 
## F-statistic:  5100 on 1 and 1858 DF,  p-value: < 2.2e-16

Interpretation:

The linear regression model shows a strong positive trend in DAX stock prices over time. The coefficient for ds (1.231) indicates that the stock price increases by approximately 1.23 units per day, reinforcing a consistent upward trajectory.

The R-squared value (0.733) suggests that 73.3% of the stock price variation is explained by time, demonstrating a strong relationship between time and price growth. The highly significant p-value (<2.2e-16) confirms that this trend is statistically significant.

Given its steady growth, strong trend, and statistical reliability, DAX appears to be a good stock option for long-term investment, particularly for those seeking consistent market appreciation.

3.3 Comparing Different Time frame

# Subset data for early (1991-1994) and late (1995-1998) periods
early_data <- eustock.df[eustock.df$ds < as.Date("1995-01-01"), ]
late_data  <- eustock.df[eustock.df$ds >= as.Date("1995-01-01"), ]

# Plot early period
ggplot(early_data, aes(x = ds, y = y)) +
  geom_line(color = "red") +
  labs(title = "DAX (1991-1994)", x = "Year", y = "Stock Price") +
  theme_minimal()

# Plot late period
ggplot(late_data, aes(x = ds, y = y)) +
  geom_line(color = "green") +
  labs(title = "DAX (1995-1998)", x = "Year", y = "Stock Price") +
  theme_minimal()

Observations:

The market was relatively stable early on. Steeper growth is visible in the late 1990s, possibly due to stronger economic conditions.

Section 4:Prophet Forecasting

# Create Prophet model
m <- prophet(eustock.df)
## Disabling weekly seasonality. Run prophet with weekly.seasonality=TRUE to override this.
## Disabling daily seasonality. Run prophet with daily.seasonality=TRUE to override this.
# Generate future dates (365 days ahead)
future <- make_future_dataframe(m, periods = 365, freq = "day")

# Predict future values
forecast <- predict(m, future)

4.2 Interactive Forecast with Plotly

# Create an interactive Plotly forecast chart
forecast_plotly <- plot_ly() %>%
  add_trace(x = forecast$ds, y = forecast$yhat, type = "scatter", mode = "lines", name = "Forecast", line = list(color = "blue")) %>%
  add_trace(x = forecast$ds, y = forecast$yhat_lower, type = "scatter", mode = "lines", name = "Lower Bound", line = list(dash = "dot", color = "gray")) %>%
  add_trace(x = forecast$ds, y = forecast$yhat_upper, type = "scatter", mode = "lines", name = "Upper Bound", line = list(dash = "dot", color = "gray")) %>%
  layout(title = "DAX Stock Price Forecast (Prophet Model)",
         xaxis = list(title = "Year"),
         yaxis = list(title = "Stock Price"))

forecast_plotly  # Display the interactive forecast
forecast <- predict(m, future)

# Plot forecast
plot(m, forecast)

forecast <- predict(m, future)

Conclusion:

This project successfully analyzed historical trends of European stock indices, with a focus on DAX (Germany). Through exploratory data analysis, interactive visualizations, and statistical modeling, we identified long-term growth patterns and market fluctuations.

Using Prophet forecasting, we predicted future DAX stock prices, showing a continued upward trend with varying confidence intervals. The interactive Plotly visualization highlighted seasonality and uncertainty, while linear regression confirmed a strong positive trend over time.

By comparing different time frames, we observed market evolution, reinforcing the importance of data-driven forecasting. The combination of historical analysis, statistical modeling, and forecasting tools makes this approach a valuable framework for predicting future stock market trends.

Is DAX a Good Buy?

Based on our findings, DAX shows strong long-term growth potential, making it a good investment option for long-term investors. However, short-term fluctuations and market volatility suggest that investors should consider risk tolerance and broader economic conditions before making a decision.